package domain

import (
	"gluenet/modules/manager/server/domain/aggregate"
	"gluenet/modules/manager/server/domain/vo"
	"gluenet/modules/manager/server/infra/prepare"
	"reflect"
)

func init() {
	//fmt.Printf("domina init\n")
	prepare.RegisterService(func() {
		config := NewInstanceDomain()
		prepare.InjectDependency(func() *Instance {
			return config
		})
	})
}

func NewInstanceDomain() *Instance {
	domain := &Instance{}
	prepare.FetchDependency(&domain.InstanceFactory)
	return domain
}

type Instance struct {
	InstanceFactory *aggregate.InstanceFactory
}

//func (r *Instance) Stop(guid string) error {
//	return r.InstanceCLI.StopObject(guid)
//}
//
//func (r *Instance) Start(guid string) error {
//	return r.InstanceCLI.StartObject(guid)
//}
//
func (r *Instance) Remove(guid string, userId string) (interface{}, error) {
	return r.InstanceFactory.DeleteInstance(guid, userId)
}

//
func (r *Instance) Create(req vo.CreateInstanceReq) (interface{}, error) {
	ins, err := r.InstanceFactory.CreateInstance(req)
	if err != nil {
		return nil, err
	}
	insRes := ins.ShowInfo()
	return insRes, nil
}

//
//func (r *Instance) MarkedTag(ObjId, key, value string) error {
//	return r.TagRepo.New(ObjId, key, value)
//}

func (r *Instance) FindByUser(admin bool, userId string, query map[string]interface{}) (interface{}, error) {
	if !admin {
		query["user_id"] = userId
	}

	ins, err := r.InstanceFactory.QueryInstance(query)
	if err != nil {
		return nil, err
	}
	var insRes = make([]interface{}, len(ins))
	for index, it := range ins {
		insRes[index] = it.ShowInfo()
	}
	return insRes, nil
}

func (r *Instance) FindBy(query map[string]interface{}) (interface{}, error) {
	ins, err := r.InstanceFactory.QueryInstance(query)
	if err != nil {
		return nil, err
	}
	var insRes = make([]interface{}, len(ins))
	for index, it := range ins {
		insRes[index] = it.ShowInfo()
	}
	return insRes, nil
}

func (r *Instance) FindRuntimeBy(admin bool, userId string, query map[string]interface{}) (interface{}, error) {
	if !admin {
		query["user_id"] = userId
	}

	ins, err := r.InstanceFactory.QueryInstance(query)
	if err != nil {
		return nil, err
	}
	var insRes = make([]interface{}, len(ins)+1)
	var tags []interface{}
	for k, it := range ins {
		obj, err := it.ShowRuntimeInfo()
		if err != nil {
			return nil, err
		}
		//cfg, err := r.InstanceFactory.GetInstanceConfig(it.ConfigID, it.UserID)
		//if err != nil {
		//	return nil, err
		//}
		//obj.Version = cfg.Version
		//obj.Describe = cfg.Describe

		if k == 0 {
			e := reflect.TypeOf(obj).Elem()
			num := e.NumField()
			tags = make([]interface{}, num)
			for i := 0; i < num; i++ {
				tags[i] = e.Field(i).Tag.Get(`json`)
			}
			insRes[0] = tags
		}

		var vals = make([]interface{}, len(tags))
		e := reflect.ValueOf(obj).Elem()
		for fid := range tags {
			val := e.Field(fid).Interface()
			vals[fid] = val
		}
		insRes[k+1] = vals
	}
	return insRes, nil
}

func (r *Instance) FindRuntimeListBy(admin bool, userId string, query map[string]interface{}) (interface{}, error) {
	if !admin {
		query["user_id"] = userId
	}

	ins, err := r.InstanceFactory.QueryInstance(query)
	if err != nil {
		return nil, err
	}
	var insRes = make(map[string]interface{}, len(ins))
	for _, it := range ins {
		obj, err := it.ShowRuntimeInfo()
		if err != nil {
			return nil, err
		}
		insRes[obj.GUID] = obj
	}
	return insRes, nil
}

//func (r *Instance) FindByTag(kvs map[string]string, userID string) ([]*entity.Instance, error) {
//	ids, err := r.TagRepo.FindObjects(kvs)
//	if err != nil {
//		return nil, err
//	}
//	var ins = make([]*entity.Instance, len(ids))
//	for i, id := range ids {
//		cfg, err := r.InstanceRepo.Get(id, userID)
//		if err != nil {
//			return nil, err
//		}
//		ins[i] = cfg
//	}
//	return ins, err
//}

func (r *Instance) CreateLinks(ControGUID, AppGUID, userID string) (interface{}, error) {
	return r.InstanceFactory.LinkInstance(ControGUID, AppGUID, userID)
}

func (r *Instance) InfoStrategy(ControGUID string, AppGUID []string, userID string) (interface{}, error) {
	return r.InstanceFactory.InfoStrategy(ControGUID, AppGUID, userID)
}

//
func (r *Instance) GetLinks(ControGUID, userID string) (interface{}, error) {
	return r.InstanceFactory.QueryInstanceLinks(ControGUID, userID)
}

//
func (r *Instance) DeleteAllLinks(ControGUID string) error {
	return r.InstanceFactory.DelAllLink(ControGUID)
}

func (r *Instance) SaveReport(report *vo.InstanceReport) error {
	return r.InstanceFactory.SaveReport(report)
}

func (r *Instance) Import(req *vo.ImportInstanceReq) (interface{}, error) {
	return r.InstanceFactory.ImportInstance(req)
}

func (r *Instance) DelImport(guid, userID string) (interface{}, error) {
	return r.InstanceFactory.DeleteImportInstance(guid, userID)
}

func (r *Instance) GetInstanceContainerAgent(guid, container string) (interface{}, error) {
	return r.InstanceFactory.GetInstanceContainerAgent(guid, container)
}

func (r *Instance) GetGraphJaeger(guid, userID string) (interface{}, error) {
	return r.InstanceFactory.GetDagJaeger(guid, userID)
}

func (r *Instance) GetGraphJaegerAll(userID string) (interface{}, error) {
	return r.InstanceFactory.GetDagJaegerAll(userID)
}

func (r *Instance) UpdateGraphJaeger(userID string) error {
	return r.InstanceFactory.UpdateDagJaeger(userID)
}

func (r *Instance) GetReport(guid, container string) (interface{}, error) {
	return r.InstanceFactory.GetReport(guid, container)
}
func (r *Instance) GetFile(guid, container, url, userId string) (interface{}, error) {
	return r.InstanceFactory.GetFile(guid, container, url, userId)
}

func (r *Instance) UpdateInstanceContainer() error {
	return r.InstanceFactory.UpdateInstanceContainers()
}

func (r *Instance) GetJaegerProxy(guid string) (interface{}, error) {
	return r.InstanceFactory.JaegerProxy(guid)
}

//func (r *Instance) GetWebSSH(admin bool, userId string, query map[string]interface{}) (interface{}, error) {
//	if !admin {
//		query["user_id"] = userId
//	}
//
//	ins, err := r.InstanceFactory.QueryInstance(query)
//	if err != nil {
//		return nil, err
//	}
//	url := os.Getenv("WEBSSH")
//	console := os.Getenv("WEBCONSOLE")
//
//	var res = make([]map[string]interface{},len(ins))
//	for k,v := range ins {
//		res[k] = map[string]interface{}{
//			v.GUID: map[string]string{
//				"url": url,
//				"console": console,
//			},
//		}
//	}
//
//	return res, nil
//}
